package com.qf.service.impl.blog;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qf.api.blog.dto.CatalogArticleDTO;
import com.qf.api.blog.dto.CatalogDTO;
import com.qf.api.blog.dto.CatalogSortDTO;
import com.qf.api.blog.entity.WikiCatalogEntity;
import com.qf.api.blog.service.ArticleService;
import com.qf.api.blog.service.WikiCatalogService;
import com.qf.api.blog.vo.WikiCatalogVO;
import com.qf.core.constant.CommonConstant;
import com.qf.core.exception.BaseException;
import com.qf.core.response.ResponseCode;
import com.qf.dao.blog.mapper.WikiCatalogMapper;
import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author sin
 * @description 针对表【t_wiki_catalog(知识库目录表（两级结构）)】的数据库操作Service实现
 * @createDate 2025-05-23 14:19:29
 */
@Service
public class WikiCatalogServiceImpl extends ServiceImpl<WikiCatalogMapper, WikiCatalogEntity>
        implements WikiCatalogService {

    @Resource
    private WikiCatalogMapper wikiCatalogMapper;

    @Resource
    private ArticleService articleService;

    @Override
    public List<WikiCatalogVO> getWikiCatalog(Long wikiId) {
        List<WikiCatalogEntity> wikiCatalogs = wikiCatalogMapper.selectList(
                new LambdaQueryWrapper<WikiCatalogEntity>()
                        .eq(wikiId != null, WikiCatalogEntity::getWikiId, wikiId)
        );
        List<WikiCatalogVO> list = new ArrayList<>();
        List<WikiCatalogEntity> list1 = wikiCatalogs.stream().filter(e ->
                Objects.equals(e.getParentId(), CommonConstant.PARENT_ID)
        ).sorted(Comparator.comparing(WikiCatalogEntity::getSort)).toList();
        List<WikiCatalogEntity> list2 = wikiCatalogs.stream().filter(e ->
                !Objects.equals(e.getParentId(), CommonConstant.PARENT_ID)
        ).sorted(Comparator.comparing(WikiCatalogEntity::getSort)).toList();
        list1.forEach(w -> {
            WikiCatalogVO build = WikiCatalogVO.builder().id(w.getId()).icon(w.getIcon()).title(w.getTitle()).sort(w.getSort()).child(getChild(w.getId(), list2)).build();
            list.add(build);
        });
        return list;
    }

    @Override
    public Boolean addWikiCatalog(Long wikiId, String title, String icon) {
        // 获取当前wikiId下所有一级目录中的最大sort 如果查询为null，则默认为 0
        Integer sort = wikiCatalogMapper.getMaxSort(wikiId, CommonConstant.PARENT_ID);
        WikiCatalogEntity wikiCatalogEntity = WikiCatalogEntity
                .builder()
                .wikiId(wikiId)
                .parentId(CommonConstant.PARENT_ID)
                .sort(sort+1)
                .title(title)
                .icon(icon)
                .build();
        return wikiCatalogMapper.insert(wikiCatalogEntity) > CommonConstant.ZERO;
    }

    @Override
    @Transactional
    public void editCatalogSort(List<CatalogSortDTO> catalogSortDTOS) {
        if (CollectionUtils.isEmpty(catalogSortDTOS)) {
            throw new BaseException(ResponseCode.CATALOG_IS_NOT_EXIT);
        }
        Set<Long> ids = new HashSet<>();
        Map<Long, Integer> sortMap = new HashMap<>();
        for (CatalogSortDTO dto : catalogSortDTOS) {
            Long id = dto.getId();
            if (id == null || dto.getSort() == null) {
                throw new BaseException(ResponseCode.CATALOG_DATA_ERROR);
            }
            // 检查重复 id
            if (!ids.add(id)) {
                throw new BaseException(ResponseCode.CATALOG_DATA_ERROR);
            }
            ids.add(id);
            sortMap.put(id, dto.getSort());
        }
        // 查询实际存在的ID及对应的sort值
        List<WikiCatalogEntity> existingEntities = wikiCatalogMapper.selectByIds(ids);
        if (existingEntities.size() != ids.size()) {
            throw new BaseException(ResponseCode.CATALOG_DATA_ERROR);
        }
        // 校验排序变动
        for (WikiCatalogEntity entity : existingEntities) {
            Long id = entity.getId();
            Integer inputSort = sortMap.get(id);
            Integer dbSort = entity.getSort();
            if (Objects.equals(inputSort, dbSort)) {
                throw new BaseException(ResponseCode.CATALOG_ORDER_NOT_CHANGE);
            }
            if (Math.abs(inputSort - dbSort) > CommonConstant.MAX_VALUE) {
                throw new BaseException(ResponseCode.CATALOG_ORDER_MAX_ERROR);
            }
        }
        catalogSortDTOS.forEach(c -> wikiCatalogMapper.updateCatalogSort(c.getId(), c.getSort()));
    }

    @Override
    public Boolean updateWikiCatalog(Long id, CatalogDTO catalogDTO) {
        WikiCatalogEntity wikiCatalogEntity = WikiCatalogEntity.builder().id(id).title(catalogDTO.getTitle()).icon(catalogDTO.getIcon()).build();
        return wikiCatalogMapper.updateById(wikiCatalogEntity) > 0;
    }

    @Override
    @Transactional
    public Boolean removeWikiCatalog(Long id) {
        // 根据Id获取该Id的childId List 然后统一删除
        List<Long> childIds = wikiCatalogMapper.getChildIds(id);
        childIds.add(id);
        return wikiCatalogMapper.deleteByIds(childIds) > 0;
    }

    /**
     * 知识库添加文章
     **/
    @Override
    @Transactional
    public String addArticle(Long parentId, List<CatalogArticleDTO> articleDTOS) {
        if (articleDTOS == null || articleDTOS.isEmpty()) {
            throw new BaseException(ResponseCode.NO_DATA);
        }
        // 判断目录是否存在
        WikiCatalogEntity catalog = wikiCatalogMapper.selectById(parentId);
        if (catalog == null) {
            throw new BaseException(ResponseCode.CATALOG_IS_NOT_EXIT);
        }
        // TODO 添加了重复的文章
        Long wikiId = articleDTOS.get(0).getWikiId();
        // 获取当前wikiId下所有parentId目录中的最大sort 如果查询为null，则默认为 0
        Integer sort = wikiCatalogMapper.getMaxSort(wikiId, parentId);

        // 获取该目录下已有的文章ID，并转为 Set 以加快 contains 判断
        List<Long> articleIdList = getArticleIdsByParentId(parentId);
        Set<Long> articleIdSet = articleIdList == null ? new HashSet<>() : new HashSet<>(articleIdList);

        Set<Long> ids = new HashSet<>(); // 防止传入参数有重复
        List<WikiCatalogEntity> entityList = new ArrayList<>();
        AtomicInteger sortValue = new AtomicInteger(sort == null ? 0 : sort);

        StringBuilder repeatId = new StringBuilder("已去掉重复添加的文章Id：[");
        for (CatalogArticleDTO a : articleDTOS) {
            Long articleId = a.getId();

            // 1. 防止参数中重复
            if (!ids.add(articleId)) {
                throw new BaseException(ResponseCode.CATALOG_ADD_ARTICLE_REPEAT);
            }

            // 2. 验证文章是否存在
            if (articleService.getById(articleId) == null) {
                throw new BaseException(ResponseCode.ARTICLE_NOT_FOUND);
            }

            // 3. 如果该目录下尚未包含该文章，则新增
            if (!articleIdSet.contains(articleId)) {
                int currentSort = sortValue.incrementAndGet();
                entityList.add(WikiCatalogEntity.builder()
                        .wikiId(wikiId)
                        .parentId(parentId)
                        .articleId(articleId)
                        .title(a.getTitle())
                        .sort(currentSort)
                        .build());
            } else {
                repeatId.append(articleId);
                repeatId.append(",");
            }
        }

        wikiCatalogMapper.insert(entityList);
        String s = repeatId.substring(0, repeatId.length() - 1) + "]";
        return s.length() > "已去掉重复添加的文章Id：[".length()  ? s : null;
    }

    @Override
    public List<com.qf.api.front.vo.WikiCatalogVO> getFrontWikiCatalog(Long wikiId) {
        List<WikiCatalogEntity> wikiCatalogs = wikiCatalogMapper.selectList(
                new LambdaQueryWrapper<WikiCatalogEntity>()
                        .eq(wikiId != null, WikiCatalogEntity::getWikiId, wikiId)
        );

        // 将列表分为父级和子级，并进行排序
        Map<Long, List<WikiCatalogEntity>> catalogMap = wikiCatalogs.stream()
                .sorted(Comparator.comparing(WikiCatalogEntity::getSort))
                .collect(Collectors.groupingBy(WikiCatalogEntity::getParentId));

        // 过滤出父级元素，并构建WikiCatalogVO对象
        List<com.qf.api.front.vo.WikiCatalogVO> result = wikiCatalogs.stream()
                .filter(e -> Objects.equals(e.getParentId(), CommonConstant.PARENT_ID))
                .map(w -> {
                    // 获取子项
                    List<WikiCatalogEntity> children = catalogMap.getOrDefault(w.getId(), Collections.emptyList());
                    List<com.qf.api.front.vo.WikiCatalogVO> childrenVO = children.stream()
                            .map(c -> com.qf.api.front.vo.WikiCatalogVO.builder()
                                    .id(c.getId())
                                    .icon(c.getIcon())
                                    .title(c.getTitle())
                                    .articleId(c.getArticleId())
                                    .build())
                            .collect(Collectors.toList());
                    // 返回构建好的父级VO
                    return com.qf.api.front.vo.WikiCatalogVO.builder()
                            .id(w.getId())
                            .icon(w.getIcon())
                            .title(w.getTitle())
                            .articleId(w.getArticleId())
                            .children(childrenVO.isEmpty() ? null : childrenVO)  // 如果没有子项，则children为null
                            .build();
                })
                .filter(vo -> vo.getChildren() != null && !vo.getChildren().isEmpty())  // 过滤掉没有子项的父级
                .collect(Collectors.toList());
        return result;
    }

    private List<Long> getArticleIdsByParentId(Long parentId) {
        return wikiCatalogMapper.getArticleIdsByParentId(parentId);
    }

    protected List<WikiCatalogVO> getChild(Long parentId, List<WikiCatalogEntity> list) {
        List<WikiCatalogVO> vo = new ArrayList<>();
        list.stream().filter(w -> Objects.equals(w.getParentId(), parentId)).forEach(e -> {
            vo.add(WikiCatalogVO.builder().id(e.getId()).icon(e.getIcon()).title(e.getTitle()).sort(e.getSort()).build());
        });
        return vo;
    }
}




